﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ProtocolConversion_WINCE
{
   public  class Ping
    {
        #region lib declare
        [DllImport("coredll")]
        extern public static IntPtr LocalAlloc(int flags, int size);

        [DllImport("coredll")]
        extern public static IntPtr LocalFree(IntPtr pMem);

        [DllImport("iphlpapi")]
        extern public static IntPtr IcmpCreateFile();

        [DllImport("iphlpapi")]
        extern public static bool IcmpCloseHandle(IntPtr h);

        [DllImport("iphlpapi")]
        extern public static uint IcmpSendEcho(
                         IntPtr IcmpHandle,
                         uint DestinationAddress,
                         byte[] RequestData,
                         short RequestSize,
                         IntPtr /*IP_OPTION_INFORMATION*/ RequestOptions,
                         byte[] ReplyBuffer,
                         int ReplySize,
                         int Timeout);

        [DllImport("coredll")]
        extern static int GetLastError();
        //保存IP地址

        #endregion

        #region Class ICMP_ECHO_REPLY  declare
        public class ICMP_ECHO_REPLY
        {
            public ICMP_ECHO_REPLY(int size) { data = new byte[size]; }
            byte[] data;
            public byte[] _Data { get { return data; } }
            public int Address { get { return BitConverter.ToInt32(data, 0); } }
            public int Status { get { return BitConverter.ToInt32(data, 4); } }
            public int RoundTripTime { get { return BitConverter.ToInt32(data, 8); } }
            public short DataSize { get { return BitConverter.ToInt16(data, 0xc); } set { BitConverter.GetBytes(value).CopyTo(data, 0xc); } }
            public IntPtr Data { get { return new IntPtr(BitConverter.ToInt32(data, 0x10)); } set { BitConverter.GetBytes(value.ToInt32()).CopyTo(data, 0x10); } }
            public byte Ttl { get { return data[0x14]; } }
            public byte Tos { get { return data[0x15]; } }
            public byte Flags { get { return data[0x16]; } }
            public byte OptionsSize { get { return data[0x17]; } }
            public IntPtr OptionsData { get { return new IntPtr(BitConverter.ToInt32(data, 0x18)); } set { BitConverter.GetBytes(value.ToInt32()).CopyTo(data, 0x18); } }
        }
        #endregion

        const int LMEM_ZEROINIT = 0x40;
        //const uint ipremote = 0x6400A8C0;  //192.168.0.100==C0 A8 00 64 
        //uint ipremote = 0x63A1220A;//10.34.161.99
        uint ipremote;
        Thread threadlan;
        
        private bool isSuccessed = false;
       //关闭句柄，和分配的堆空间
        private bool isClose = false;
        
       private static  bool firstStart = true;

        public Ping(string IP)
        {
            byte[] ipByte = new byte[4];

            string[] array = IP.Split('.');
            for (int i = 0; i < array.Length; i++)
            {
                ipByte[i] = Convert.ToByte(array[i]);
            }

            ipremote = (uint)BitConverter.ToInt32(ipByte, 0);

            Init(ipremote);
        }

        public void Init(uint ip)
        {
            //ipremote = 0x63A1220A;//10.34.161.99
            ipremote = ip;
            //ipremote = 0xB801A8C0;
            threadlan = new Thread(threadchecklan);
            threadlan.IsBackground = true;
            threadlan.Start();
        }

        private void threadchecklan()
        {
                firstStart = false;
                byte[] RequestData = Encoding.ASCII.GetBytes(new string('\0', 64));
                ICMP_ECHO_REPLY reply = new ICMP_ECHO_REPLY(255);
                reply.DataSize = 255;
                IntPtr pData = LocalAlloc(LMEM_ZEROINIT, reply.DataSize);
                reply.Data = pData;
                IntPtr h = IcmpCreateFile();         
            while (true)
            {
                if (isClose)
                {
                    IcmpCloseHandle(h);
                    LocalFree(reply.Data);
                    return;
                }
                
                uint ret = IcmpSendEcho(h, ipremote, RequestData, (short)RequestData.Length, IntPtr.Zero, reply._Data, reply._Data.Length, 1000);
                if (ret != 0)
                {
                    isSuccessed = true;
                }
                else
                {
                    isSuccessed = false;
                }
                Thread.Sleep(100);
            }


            //IcmpCloseHandle(h);
            //LocalFree(reply.Data);
        }
       //释放句柄，和堆栈空间
        public void ClosePing()
        {
            isClose = true;
            threadchecklan();
            threadlan.Abort();
        }

        public bool GetPingResult()
        {
            //threadchecklan();
            return isSuccessed;
        }
    }
}
